<?php

namespace App\Service\Vip;

use App\Common\Message;
use App\Enum\EnumType;
use App\Service\BaseService;
use Hyperf\DbConnection\Db;

/**
 * VIP服务
 */
class VipService extends BaseService
{
    // 表名
    protected static string $tbName = 'act_task';
    // 缓存表
    protected static int $cacheDb = 2;

    /**
     * 用户升级VIP等级
     * @param $user
     * @return false|mixed|void
     */
    public static function vipUpgrade($user)
    {
        try {
            $uid = $user['uid'];
            $oldVip = $user['vip'];
            $currTime = time();
            // 获取vip升级配置
            $vipConf = self::getVipConf();
            if (empty($vipConf)) {
                self::logger()->alert('VipService.vipUpgrade.Alert：获取VIP升级配置失败');
                return false;
            }

            // 检测用户应该升级的VIP等级与升级奖励
            $vipLog = [];
            foreach ($vipConf as $conf) {
                if ($conf['vip'] > $oldVip && $conf['need_pay_price'] <= $user['total_pay_score']) {
                    $vipLog[] = [
                        'uid' => $uid,
                        'vip' => $conf['vip'],
                        'order_money' => $user['total_pay_score'],
                        'type' => 1,
                        'amount' => $conf['sj_amount'],
                        'bonus' => $conf['sj_bonus'],
                        'createtime' => $currTime,
                    ];
                }
            }

            // 没有升级奖励，返回false
            if (empty($vipLog)) {
                return false;
            }

            $upgradeVipLevel = max(array_column($vipLog, 'vip')); // 用户应该升级的VIP等级
            Db::transaction(function () use ($vipLog, $uid, $upgradeVipLevel) {
                // 保存vip升级奖励记录
                self::getPoolTb('vip_log')->insert($vipLog);

                // 更新用户vip等级
                self::getPoolTb('userinfo')->where('uid', $uid)->update(['vip' => $upgradeVipLevel]);
            });

            //升级消息
            if ($oldVip == 6){
                Message::messageSelect(3, ['uid' => $uid]);
            }else{
                Message::messageSelect(2, ['uid' => $uid, 's1' => $oldVip]);
            }

            return $upgradeVipLevel;
        } catch (\Throwable $ex) {
            self::writeExceptionMsg($ex, __CLASS__.'.'.__FUNCTION__);
        }

    }

    /**
     * 获取VIP配置
     * @return array|mixed[]|\Redis
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     * @throws \RedisException
     */
    protected static function getVipConf()
    {
        // 从缓存读取配置
        $cache = self::cacheConn(dbIndex: self::$cacheDb);
        $cacheData = $cache->hGetAll(EnumType::VIP_CONF_CACHE_KEY);
        if (empty($cacheData)) {
            // 缓存不存在则从数据库获取
            $vipConf = self::getPoolTb('vip', 'readConfig')
                ->select('id', 'need_pay_price', 'sj_amount', 'vip', 'sj_bonus', 'betrayal_bili')
                ->orderBy('vip')
                ->get()->toArray();
            foreach ($vipConf as $value) {
                $cacheData[$value['vip']] = json_encode($value);
            }
            // 存入缓存
            $cache->hMSet(EnumType::VIP_CONF_CACHE_KEY, $cacheData);
        }

        foreach ($cacheData as $key => $value) {
            $cacheData[$key] = json_decode($value, true);
        }

        return $cacheData;
    }

    /**
     * 获取上一天用户输钱反水奖励
     * @param $uid
     * @return array|bool|\Redis
     */
    public static function getLastDayBetAwards($uid): array|bool|\Redis
    {
        try {
            // 获取用户信息
            $user = self::getPoolTb('userinfo')->where('uid', $uid)->first(['uid', 'vip']);
            // vip配置
            $vipConf = self::getVipConf();
            $uvConf = $vipConf[$user['vip']] ?? [];
            if (empty($uvConf)) {
                return false;
            }

            // 从缓存获取
            $expireTime = 60 * 60 * 24;
            $lastDay = date('Ymd', strtotime('-1 day'));
            $cacheKey = EnumType::VIP_LAST_DAY_BET_AWARDS_CACHE_KEY . $lastDay . '_' . $uid;
            // 从缓存获取输钱奖励
            $cache = self::cacheConn(dbIndex: self::$cacheDb);
            $cacheData = $cache->hGetAll($cacheKey);
            if ($cacheData) {
                // vip等级发生变化，重新计算奖励
                if ($cacheData['status'] == 0 && $cacheData['vip'] != $user['vip'] && $cacheData['lose_water'] > 0) {
                    $cacheData['awards'] = bcdiv(bcmul($cacheData['lose_water'], $uvConf['betrayal_bili']), 100);
                    $cache->hMSet($cacheKey, $cacheData);
                }
                return $cacheData;
            }

            // 获取用户前一天输钱流水
            $userDayLoseWater = self::getPartTb('slots_log', $lastDay)
                ->where('uid', $uid)
                ->where('is_settlement', 1)
                ->where('cashTransferAmount', '<', 0)
                ->sum('cashTransferAmount');
            $data = [
                'uid' => $uid,
                'vip' => $user['vip'],
                'lose_water' => 0,
                'awards' => 0,
                'status' => 0,
                'cache_key' => $cacheKey,
            ];
            $userDayLoseWater = abs($userDayLoseWater);
            // 计算反水奖励
            if  ($userDayLoseWater > 0) {
                $data['lose_water'] = $userDayLoseWater;
                $data['awards'] = bcdiv(bcmul($userDayLoseWater, $uvConf['betrayal_bili']), 100);
            }
            $cache->hMSet($cacheKey, $data);
            $cache->expire($cacheKey, $expireTime);

            return $data;
        } catch (\Throwable $ex) {
            self::writeExceptionMsg($ex, __CLASS__.'.'.__FUNCTION__);
            return false;
        }
    }

    /**
     * 领取日奖励
     * @param $uid
     * @return mixed
     */
    public static function acceptDailyAwards($uid): mixed
    {
        try {
            $currTime = time();
            $userAwards = self::getLastDayBetAwards($uid);
            if ($userAwards === false || $userAwards['status'] == 1 || $userAwards['awards'] <= 0) {
                return false;
            }

            // 新增领取记录
            self::getPoolTb('vip_log')->insert([
                'uid' => $uid,
                'vip' => $userAwards['vip'],
                'type' => 4,
                'bonus' => $userAwards['awards'],
                'status' => 1,
                'createtime' => $currTime,
                'receivetime' => $currTime,
            ]);

            // 更新缓存中数据领取状态
            self::setFieldCache($userAwards['cache_key'], 'status', 1, dbIndex: self::$cacheDb);
            return $userAwards['awards'];
        } catch (\Throwable $ex) {
            self::writeExceptionMsg($ex, __CLASS__.'.'.__FUNCTION__);
            return false;
        }
    }

    /**
     * 领取月奖励
     * @param $user
     * @return bool
     */
    public static function acceptMonthAwards($user): bool
    {
        try {
            $currTime = time();
            // 检测本月是否已经领取过
            $monthStartTime = strtotime(date('Y-m-01'));
            $existNum = self::getPoolTb('vip_log')
                ->where('uid', $user['uid'])
                ->where('type', 3)
                ->where('status', 1)
                ->where('receivetime', '>=', $monthStartTime)
                ->count();
            if ($existNum) {
                return false;
            }

            // 新增领取记录
            self::getPoolTb('vip_log')->insert([
                'uid' => $user['uid'],
                'vip' => $user['vip'],
                'type' => 3,
                'amount' => $user['month_amount'],
                'bonus' => $user['month_bonus'],
                'status' => 1,
                'createtime' => $currTime,
                'receivetime' => $currTime,
            ]);

            return true;
        } catch (\Throwable $ex) {
            self::writeExceptionMsg($ex, __CLASS__.'.'.__FUNCTION__);
            return false;
        }
    }

    /**
     * 获取奖励领取状态
     * @param $uid
     * @param $type
     * @param $startTime
     * @return int
     */
    public static function getAcceptAwardsStatus($uid, $type, $startTime): int
    {
        // 检测当前时间节点是否已经领取过
        return self::getPoolTb('vip_log')
            ->where('uid', $uid)
            ->where('type', $type)
            ->where('status', 1)
            ->where('receivetime', '>=', $startTime)
            ->count();
    }

    /**
     * 获取vip领取记录
     * @param array $params
     * @return array
     */
    public static function getVipLog(array $params): array
    {
        $dataType  = $params['data_type'] ?? 'all';
        $logObj = self::getPoolTb('vip_log')
            ->where('uid', $params['uid'])
            ->where('status', 1)
            ->select('id', 'uid', 'vip', 'type', 'amount', 'bonus', 'createtime', 'receivetime');
        if ($dataType == 'month') {
            $currMonthTime = strtotime(date('Y-m-01'));
            $logObj->where('receivetime', '>=', $currMonthTime);
        }
        // 统计总领取奖励
        $totalAwards = 0;
        if (!isset($params['page']) || $params['page'] == 1) {
            $totalAwards = $logObj->sum('bonus');
        }

        // 分页数据记录
        $logList = $logObj->paginate(self::$pageSize)->toArray();
        foreach ($logList['data'] as &$v) {
            $v['createtime'] = date(self::$dateTimeFormat, $v['createtime']);
            $v['receivetime'] = date(self::$dateTimeFormat, $v['receivetime']);
        }
        return [
            'current_page' => $logList['current_page'],
            'data' => $logList['data'],
            'last_page' => $logList['last_page'],
            'total_num' => $logList['total'],
            'total_awards' => $totalAwards,
        ];
    }
}